/*
 * Copyright (C) 2009 Las Cumbres Observatory (lcogt.net)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package org.lcogt.tools.fitsviewer.server;

import java.io.*;
import java.util.Properties;

import javax.servlet.ServletContext;

import org.lcogt.tools.fitsviewer.client.FitsDataService;

import nom.tam.fits.Fits;
import nom.tam.fits.FitsException;
import nom.tam.fits.ImageHDU;
import nom.tam.image.ImageTiler;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class FitsDataServiceImpl extends RemoteServiceServlet implements FitsDataService{
	Fits fits;
	ImageHDU imageHDU;
	ImageTiler imageTiler;
	String basePath;
	String currentPath;
	Properties prop;
	
	public int[] getFitsData(String fileName, int xPixel, int yPixel,int xEndPixel, int yEndPixel,int picHeight,int picWidth) {
		//Finds Path on server
		if(prop == null)
		{
			prop = new Properties();
			ServletContext context = getServletContext();
			InputStream is = context.getResourceAsStream("FitsViewer.properties");
			try {
				prop.load(is);
				basePath = prop.getProperty("serverPathOfFitsFiles");
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if(xPixel < 1)
			return null;
		if(yPixel < 1)
			return null;
		if(fits == null || !currentPath.equals(fileName))
		{
			try {
				
				fits = new Fits(new File(basePath+fileName));
			} catch (FitsException e) {
				e.printStackTrace();
			}
		}
		try {
				//Checks that the correct fits image is loaded
				if(imageHDU == null || !currentPath.equals(fileName))
				{
					imageHDU = (ImageHDU) fits.readHDU();
					currentPath = fileName;
				}
				
				imageTiler = (ImageTiler) imageHDU.getTiler();
				//Calculates height and width of tile
				int width = Math.abs(xEndPixel-xPixel)+1;
				int height = Math.abs(yEndPixel-yPixel)+1;
				int dataHeight = height;
				int dataWidth = width;
				int xMin;
				int yMin;
				//Handles Edge cases
				if(xPixel > xEndPixel)
					xMin = xEndPixel;
				else
					xMin = xPixel;
				if(yPixel > yEndPixel)
					yMin = yEndPixel;
				else
					yMin = yPixel;
				double slope = ((double)(yEndPixel-yPixel)/(double)(xEndPixel-xPixel));
				if(xMin<0)
					xMin = 0;
				if(yMin<0)
					yMin = 0;
				if(xMin + width > picWidth)
					dataWidth = (xMin + width)-picWidth;
				if(yMin + height > picHeight)
					dataHeight = (yMin + height)-picHeight;
				
				/*
				 * Gets data along line drawn based on slope and starting point
				 * Horizontal and Vertical Graphs are passed as single width or length
				 */
				short[] img;
				img = (short[])imageTiler.getTile(new int[]{yMin, xMin}, new int[]{dataHeight,dataWidth}); //Note getTile is y,x not x,y
				int[] intImg = new int[img.length];
				int[] intImgCopy = new int[img.length+2];
				int maxPixelValue = 0;
				for(int i = 0; i < img.length;i++)
				{
					intImg[i]= (int) ((int)img[i] * imageHDU.getBScale() + imageHDU.getBZero());
					intImgCopy[i+2] = (int) ((int)img[i] * imageHDU.getBScale() + imageHDU.getBZero());
					if(maxPixelValue < intImg[i])
						maxPixelValue = intImg[i];
				}
				intImgCopy[0] = maxPixelValue;
				int fullWidthHalfMax=0;
				for(int i = 0; i <intImg.length;i++)
				{
					if(intImg[i] >= (maxPixelValue/2))
						fullWidthHalfMax++;
				}
				intImgCopy[1]= fullWidthHalfMax;
				if(width == 1 || height == 1)
					return intImgCopy;
				else
				{
					//creates 2D array of the data
					int[][] img2 = new int[width][height];
					int index = 0;
					for(int i = 0; i < height;i++)
					{
						for(int j = 0; j < width;j++)
						{
							img2[j][i]= intImg[index];								
							index++;
						}
					}
					int[] values = new int[width];
					
	
					if(slope>0)
					{	
						for(int i = 0; i < width; i++)
						{
							values[i] = img2[i][(int)(i*slope)]; 
						}
					}
					else
					{
						for(int i = 0; i < width;i++)
						{
							values[i] = img2[i][(int)(((i*slope) + height))-1];
						}
					}
					
					/*
					 * Calulates FWHM
					 */
					int max = 0;
					for(int i = 0; i < values.length;i++)
					{
						if(values[i] >  max)
							max = values[i];
					}
					fullWidthHalfMax=0;
					for(int i = 0; i <values.length;i++)
					{
						if(values[i] >= (max/2))
							fullWidthHalfMax++;
					}
					int[] fullWidthHalfMaxValues = new int[values.length+2];
					
					fullWidthHalfMaxValues[0]=  max;
					fullWidthHalfMaxValues[1] = fullWidthHalfMax;
					
					for(int i = 0; i < values.length; i++)
					{
						fullWidthHalfMaxValues[i+2]= values[i];
					}
					return fullWidthHalfMaxValues;
				}
				
				
		} catch (FitsException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}catch (Exception e){
				e.printStackTrace();
			}
		
			return null;
	}	
}
	

